package com.mega.fe.util;

import com.mega.fe.Unravel;
import com.mega.fe.common.FuckEntityList;
import com.mega.fe.fuck.DeathInv;
import com.mega.fe.mixins.ClientLevelAccessor;
import com.mega.fe.mixins.EntityTickListAccessor;
import com.mega.fe.mixins.ServerLevelAccessor;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Pose;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.entity.EntityTickList;
import net.minecraft.world.level.gameevent.GameEvent;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;

public class AttackUtil {
    public static void die(Player player, Entity entity) {
        die(player, entity, false);
    }
    public static void die(Player player, Entity entity, boolean supermode) {
        if (BaseInit.isDeath(entity))
            return;
        Level level = entity.level();
        if (entity instanceof LivingEntity l) {
            l.deathTime = 19;
            l.activeEffects.clear();
            l.hurtTime = Integer.MAX_VALUE;
            l.deathScore = 0;
            l.setInvulnerable(false);
            l.invulnerableDuration = 0;
            l.setCustomName(Component.empty());
            l.setNoGravity(true);

            l.getEntityData().set(LivingEntity.DATA_HEALTH_ID, 0.0F);
            if (l instanceof Player p) {
                try {
                    MEGA.replaceClass(p.getInventory(), DeathInv.class);
                } catch (Throwable e) {
                    throw new RuntimeException(e);
                }
            }
            DamageSource source = l.damageSources().mobAttack(player);
            LivingEntity livingentity = l.getKillCredit();
            if (l.deathScore >= 0 && livingentity != null) {
                livingentity.awardKillScore(l, l.deathScore, source);
            }
            if (l.isSleeping()) {
                l.stopSleeping();
            }
            l.dead = true;
            l.getCombatTracker().recheckStatus();
            try {
                if (level instanceof ServerLevel serverlevel) {
                    if (source.getEntity() == null || source.getEntity().killedEntity(serverlevel, l)) {
                        l.gameEvent(GameEvent.ENTITY_DIE);
                        l.dropAllDeathLoot(source);
                        l.createWitherRose(livingentity);
                    }

                    level.broadcastEntityEvent(l, (byte) 3);
                }
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }

            l.setPose(Pose.DYING);
            if (level.isClientSide) {
                ClientLevel cl = Minecraft.getInstance().level;
                assert cl != null;
            }
            new Thread(() -> {
                try {
                    Thread.sleep(100);
                    if (level.isClientSide) {
                        ClientLevel cl = Minecraft.getInstance().level;
                        cl.removeEntity(l.getId(), Entity.RemovalReason.KILLED);
                        EntityTickList entityTickList = ((ClientLevelAccessor) cl).entityList();
                        EntityTickListAccessor accessor = (EntityTickListAccessor) entityTickList;
                        accessor.active().remove(l.getId());
                        if (MEGA.KLASS_PTR(entityTickList) != FuckEntityList.klass_ptr)
                            MEGA.replaceClass(entityTickList, FuckEntityList.class);
                        l.setRemoved(Entity.RemovalReason.KILLED);
                        l.onClientRemoval();
                    }
                    if (!level.isClientSide) {
                        assert level instanceof ServerLevel;
                        ServerLevel sl = (ServerLevel) level;
                        EntityTickList entityTickList = ((ServerLevelAccessor) sl).entityTickList();
                        EntityTickListAccessor accessor = (EntityTickListAccessor) entityTickList;
                        accessor.active().remove(l.getId());
                            if (MEGA.KLASS_PTR(entityTickList) != FuckEntityList.klass_ptr)
                                MEGA.replaceClass(entityTickList, FuckEntityList.class);
                    }
                    l.setId(-1);
                    l.dead = true;
                    l.setInvisible(true);
                    l.xo = l.xOld = l.yo = l.yOld = l.zo = l.zOld = l.zza = l.yya = l.xxa = Float.POSITIVE_INFINITY;
                    l.kill();
                    l.setPos(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
                    if (supermode) {
                        MEGA_SUPER.Attack_Target(entity);
                    }
                    Unravel.out("Entity%s already killed.", l);
                    BaseInit.addDeath(l);
                    MethodHandle suspend0 = MEGA.IMPL_LOOKUP().findVirtual(Thread.class, "suspend0", MethodType.methodType(void.class));
                    suspend0.bindTo(Thread.currentThread()).invoke();
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }
            }).start();
        }
    }
}
